﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Xml.Serialization;
using System.IO;
using Urbania.Utilities;

namespace Urbania.GUI.Elements
{
    [Serializable]
    [XmlRoot("Button")]
    public class Button : GUIElement
    {
        public enum DesignType { Type1 = 1, Type2 };

        protected Rectangle bounds;
        protected String text;
        protected DesignType designType;
        protected Texture2D sprite;
        protected SpriteFont font;
        protected string fontPath;
        protected Color fontColor;
        protected String scriptFilePath;
        protected string buttonName;
        protected bool isStatButton = false;
        protected World.Tile o;
        protected string[] specialArgs;
        public static bool screen = true;

        public string Title { get { return this.buttonName; } set { this.buttonName = value; } }
        public string Text { get { return this.text; } set { this.text = value; } }
        public int DesignTypeInt { get { return (int)this.designType; } set { this.designType = (DesignType)value; } }
        public string Script { get { return this.scriptFilePath; } set { this.scriptFilePath = value; } }
        public Rectangle Bounds { get { return this.bounds; } set { this.bounds = value; } }
        public GUIElement Parent { get { return this.parent; } }
        public string FontPath { get { return this.fontPath; } set { this.fontPath = value; } }

        public Button()
        {
            this.sprite = Utilities.Loader.GetTex("button1");
            this.font = Utilities.Loader.GetFont("Font\\default");
            this.fontPath = "Font\\default";
            this.text = "Test";
            this.bounds = new Rectangle(0, 0, (int)(font.MeasureString(this.text).X + 10), (int)(font.MeasureString(this.text).Y + 10));
            this.designType = DesignType.Type1;
            this.fontColor = Color.White;
            this.buttonName = "defualt";
            this.scriptFilePath = null;
            this.parent = null;
            this.position = new Vector2(bounds.X, bounds.Y);
        }

        public Button(string buttonName, Vector2 position, String text, int designType, ref LuaVM lua, string scriptPath, GUIElement parent)
        {
            this.sprite = Utilities.Loader.GetTex("button" + (int)designType);
            this.font = Utilities.Loader.GetFont("Font\\default");
            this.fontPath = "Font\\default";
            this.bounds = new Rectangle((int)position.X, (int)position.Y, (int)(font.MeasureString(text).X + 10), (int)(font.MeasureString(text).Y + 10));
            this.text = text;
            this.designType = (DesignType)designType;
            this.fontColor = Color.White;
            this.lua = lua;
            this.scriptFilePath = scriptPath;
            this.buttonName = buttonName;
            Utilities.Loader.LoadScriptFile(this.scriptFilePath);
            this.parent = parent;
            this.position = new Vector2(bounds.X, bounds.Y);
        }

        public Button(string buttonName, Vector2 position, String text, int designType, ref LuaVM lua, string scriptPath, string fontPath, GUIElement parent)
        {
            this.sprite = Utilities.Loader.GetTex("button" + (int)designType);
            this.font = Utilities.Loader.GetFont(fontPath);
            this.fontPath = fontPath;
            this.bounds = new Rectangle((int)position.X, (int)position.Y, (int)(font.MeasureString(text).X + 10), (int)(font.MeasureString(text).Y + 10));
            this.text = text;
            this.designType = (DesignType)designType;
            this.fontColor = Color.White;
            this.lua = lua;
            this.scriptFilePath = scriptPath;
            this.buttonName = buttonName;
            Utilities.Loader.LoadScriptFile(this.scriptFilePath);
            this.parent = parent;
            this.position = new Vector2(bounds.X, bounds.Y);
        }

        public override void Load()
        {
            Utilities.Loader.LoadScriptFile(this.scriptFilePath);
            Utilities.Loader.LoadTex("button" + this.DesignTypeInt);
            this.sprite = Utilities.Loader.GetTex("button" + this.DesignTypeInt);
        }

        public override void Update(GameTime gameTime)
        {
            bool inBounds;
            if (screen)
            {
                inBounds = (MouseWrap.PositionScreen.X <= bounds.Right) &&
                            (MouseWrap.PositionScreen.X >= bounds.X) &&
                            (MouseWrap.PositionScreen.Y <= bounds.Bottom) &&
                            (MouseWrap.PositionScreen.Y >= bounds.Y);
            } else 
            inBounds = (MouseWrap.PositionWorld.X <= bounds.Right) &&
                            (MouseWrap.PositionWorld.X >= bounds.X) &&
                            (MouseWrap.PositionWorld.Y <= bounds.Bottom) &&
                            (MouseWrap.PositionWorld.Y >= bounds.Y);
            if (inBounds)
                    this.fontColor = Color.Yellow;
            else
                this.fontColor = Color.White;

            if (MouseWrap.wasReleased(0) && inBounds)
                if (this.isStatButton)
                    this.OnClick(o);
                else
                    this.OnClick();
        }

        public override void Update(GameTime gameTime, MouseState mouse)
        {
            bool inBounds = (MouseWrap.PositionScreen.X <= bounds.Right) &&
                            (MouseWrap.PositionScreen.X >= bounds.X) &&
                            (MouseWrap.PositionScreen.Y <= bounds.Bottom) &&
                            (MouseWrap.PositionScreen.Y >= bounds.Y);
            if (inBounds)
                this.fontColor = Color.Yellow;
            else
                this.fontColor = Color.White;

            if (mouse.LeftButton == ButtonState.Pressed && inBounds)
                if (this.isStatButton)
                    this.OnClick(o);
                else
                    this.OnClick();
        }

        public void Update(GameTime gameTime, Vector2 mouse, bool mouseClicked)
        {
            bool inBounds = (mouse.X <= bounds.Right) &&
                            (mouse.X >= bounds.X) &&
                            (mouse.Y <= bounds.Bottom) &&
                            (mouse.Y >= bounds.Y);
            if (inBounds)
                this.fontColor = Color.Yellow;
            else
                this.fontColor = Color.White;

            if (mouseClicked && inBounds)
            {
                if (this.isStatButton)
                    this.OnClick(o);
                else
                    this.OnClick();
            }
        }

        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            Rectangle r = new Rectangle((int)(parent.GetPosition().X + bounds.X), (int)(parent.GetPosition().Y + bounds.Y), bounds.Width, bounds.Height);
            spriteBatch.Draw(sprite, r, Color.White);
            spriteBatch.DrawString(font, text, parent.GetPosition() + new Vector2(2 + bounds.X, 5 + bounds.Y),fontColor);
        }

        public void OnClick()
        {
            if (scriptFilePath == null)
                return;

            string tempString = Utilities.Loader.GetScriptFile(scriptFilePath);
            lua.LuaVirtual.DoFile(tempString);
        }

        public void OnClick(World.Tile o)
        {
            lua.LuaVirtual.DoFile(Utilities.Loader.GetScriptFile(this.Title + ".lua"));
            string preComp = this.buttonName;
            preComp += "(" + o.PosIndex.X + "," + o.PosIndex.Y;
            //preComp += ",'" + this.text + "'";
            foreach (string s in this.specialArgs)
            {
                preComp += "," + "'" + s + "'";
            }

            preComp += ")";

            lua.LuaVirtual.DoString(preComp);
            this.parent.toRemove = true;
        }

        public void UseSpecialUpdate(World.Tile t, params string[] args)
        {
            this.isStatButton = true;
            this.o = t;
            this.specialArgs = args;
        }
    }
}
